﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CefSharpEmbedCppRunTime
{
    public class SemanticVersion : IComparable
    {
        public static SemanticVersion GetMinVersion(SemanticVersion v1, SemanticVersion v2)
        {
            if (v1 != null && v1.CompareTo(v2) >= 0)
            {
                return v2;
            }
            return v1;
        }

        public static SemanticVersion GetMaxVersion(SemanticVersion v1, SemanticVersion v2)
        {
            if (v1 != null && v1.CompareTo(v2) >= 0)
            {
                return v1;
            }
            return v2;
        }

        public readonly Version Version;

        public readonly string Release;

        private readonly string _original;

        public static SemanticVersion TryParse(string s)
        {
            if (string.IsNullOrEmpty(s)) return null;
            var builder = new StringBuilder();
            foreach (char c in s)
            {
                if (char.IsDigit(c) || c == '.') builder.Append(c);
            }
            var text = builder.ToString();
            int length = text.Length;
            if (text.EndsWith("."))
            {
                text = text.Substring(0, text.Length - 1);
            }

            System.Version result;
            if (!TryParseVersion(text, out result))
            {
                return null;
            }

            string text2 = s.Substring(length).Trim();
            if (text2.StartsWith("-"))
            {
                text2 = text2.Substring(1).Trim();
            }
            return new SemanticVersion(s, result, text2);
        }

        private static bool TryParseVersion(string input, out Version version)
        {
            try
            {
                version = new Version(input);
                return true;
            }
            catch
            {
                version = default(Version);
                return false;
            }
        }

        public int CompareTo(object obj)
        {
            SemanticVersion semanticVersion = obj as SemanticVersion;
            if (semanticVersion == null)
            {
                return 1;
            }
            int num = Version.CompareTo(semanticVersion.Version);
            if (num != 0)
            {
                return num;
            }
            if (Release == semanticVersion.Release)
            {
                return 0;
            }
            if (Release == "")
            {
                return 1;
            }
            if (semanticVersion.Release == "")
            {
                return -1;
            }
            return String.Compare(Release.ToLowerInvariant(), semanticVersion.Release.ToLowerInvariant(), StringComparison.Ordinal);
        }

        public override bool Equals(object obj)
        {
            SemanticVersion semanticVersion = obj as SemanticVersion;
            if (semanticVersion == null)
            {
                return false;
            }
            if (semanticVersion.Version.Equals(Version))
            {
                return semanticVersion.Release.ToLowerInvariant().Equals(Release.ToLowerInvariant());
            }
            return false;
        }

        public override int GetHashCode()
        {
            return Version.GetHashCode() * 37 + Release.GetHashCode();
        }

        public override string ToString()
        {
            return _original;
        }

        private SemanticVersion(string original, Version version, string release)
        {
            _original = original;
            Version = version;
            Release = release;
        }
    }
}
